package gsp420;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import gsp420.math.RectF;
import gsp420.math.V2F;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements KeyListener , Runnable
{
	/** singleton reference to the {@link GamePanel} */
	private static GamePanel s_instance;

	/** the singleton access function */
	public static GamePanel getInstance(){
		if(s_instance == null)
			s_instance = new GamePanel();
		return s_instance;
	}
	
	/** allows for a multiton */
	private static Vector<GamePanel> s_instances = new Vector<GamePanel>();
	/** how to get the multiton ID */
	public static int getNextMultitonID(){return s_instances.size();}
	/** the multiton access function */
	public static GamePanel getInstance(int a_id){
		if(a_id < 0 || a_id > s_instances.size())
			throw new IllegalStateException("invalid multiton ID. must be 0 >= id < "+s_instances.size());
		if(s_instances.size() == a_id)
			s_instances.add(new GamePanel());
		return s_instances.get(a_id);
	}

	private static final long serialVersionUID = 1L;

	public static void main(String[] args)
	{
		Image img = null;
		try{
			img = Toolkit.getDefaultToolkit().createImage("img.png");
		}catch(Exception e){e.printStackTrace();}
		System.out.println("Hello!");
		JFrame jf = new JFrame("test");
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setSize(640, 480);
		GamePanel gp = GamePanel.getInstance();
		gp.setImage(img);
		jf.add(gp);
		jf.setVisible(true);
		jf.addKeyListener(gp);
		gp.requestFocus();
	}
	/** the game element controlled by the user */
	RectF player = new RectF();
	/** speed/direction of the player */
	V2F velocity = new V2F();
	/** speed multiplier */
	float speed = 10;
	/** game element that wins when the user controlled element reaches it*/
	RectF winZone = new RectF();
	/** the thread that is running the {@link #run} method */
	Thread m_thread;
	/** state of the {@link #run} loop */
	boolean m_running = true;
	/** color of the {@link #winZone} */
	Color winZoneColor;
	/** the image of the player element */
	Image img;
	/** font to display game size with */
	Font outputFont;

	/** made private so that the singleton can enforce the single-ness */
	private GamePanel()
	{
		try{outputFont = new Font("Algerian", Font.PLAIN, 200);
		}catch(Exception e){outputFont = null;}
		player.set(10, 20, 20, 30);
		winZone.set(100, 200, 250, 350);
		addKeyListener(this);
		m_thread = new Thread(this);
		m_thread.start();
	}
	//http://www.youtube.com/watch?v=NGFhc8R_uO4	
	void setImage(Image img){
		this.img = img;
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		if(outputFont != null)
		{
			g.setColor(Color.white);
			g.setFont(outputFont);
		}
		g.drawString("w"+getWidth()+" h"+getHeight(), 10, getHeight()-30);
		if(img != null){
			int xoffset = (int)(img.getWidth(null)-player.getWidth())/2;
			int yoffset = (int)(img.getWidth(null)-player.getWidth())/2;
			int x = (int)player.p0.x - xoffset;
			int y = (int)player.p0.y - yoffset;
			g.drawImage(img, x, y, null);
		}
		g.setColor(Color.blue);
		player.draw(g);
		g.setColor(winZoneColor);
		winZone.draw(g);
	}
	@Override
	public void keyPressed(KeyEvent arg0) {
		switch(arg0.getKeyCode()){
		case KeyEvent.VK_LEFT:	velocity.x--;	break;
		case KeyEvent.VK_UP:	velocity.y--;	break;
		case KeyEvent.VK_RIGHT:	velocity.x++;	break;
		case KeyEvent.VK_DOWN:	velocity.y++;	break;
		case KeyEvent.VK_SPACE:	velocity.x = 0; velocity.y = 0;	break;
		}
	}
	@Override
	public void keyReleased(KeyEvent arg0) {}
	@Override
	public void keyTyped(KeyEvent arg0) {}

	void update(float seconds)
	{
		player.translate(velocity.product(seconds*speed));
		winZoneColor = player.isColliding(winZone)?Color.green:Color.white;
	}
	
	@Override
	public void run() {
		long now, then = System.currentTimeMillis(), passed;
		float seconds;
		while(m_running){
			// timing calculations
			now = System.currentTimeMillis();
			passed = now - then;
			then = now;
			seconds = passed/1000.0f;
			// update
			update(seconds);
			// draw
			repaint();
			// throttle code
			try {Thread.sleep(10);} catch (InterruptedException e) {}
		}
	}	
}
